package net.esj.basic.dao.jdbc;

import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.Map.Entry;

import net.esj.basic.core.engine.annotation.Ignore;
import net.esj.basic.dao.ann.InitializationSelection;
import net.esj.basic.dao.querybuilder.AbstractQueryBuilder;
import net.esj.basic.dao.querybuilder.QueryBuilder;
import net.esj.basic.dao.querybuilder.SymbolExpression;
import net.esj.basic.utils.hibe.HiCriteria;

import org.hibernate.criterion.MatchMode;

public class JdbcQueryBuilder<T> extends AbstractQueryBuilder<T> {

	/**
	 * 
	 */
	private static final long serialVersionUID = 4468955817350606574L;
	
	private StringBuilder sqlBuilder ;
	
	private Map<String,TableColumn> tableColumns;
	
	private StringBuilder whereSql;
	
	protected JdbcQueryBuilder(Class clazz) {
		super(clazz);
		
		if(!clazz.isAssignableFrom(InitializationSelection.class)){
			throw new IllegalArgumentException("JdbcQueryBuilder对象必须为"+InitializationSelection.class.getSimpleName()+"的子类");
		}
		
		sqlBuilder = new StringBuilder();
		whereSql = new StringBuilder();
		tableColumns = new HashMap<String, TableColumn>();
		//createTableColumn(selections);
		generateSql();
	}

	@Override
	public QueryBuilder OrderByAsc(String propertyName) {
		return this;
	}

	@Override
	public QueryBuilder OrderByDesc(String propertyName) {
		return null;
	}

	@Override
	public QueryBuilder allEq(Map propertyNameValues) {
		for(Object object:propertyNameValues.entrySet()){
			Map.Entry entry = (Entry) object;
			whereSql.append(entry.getKey().toString()).append(" = ").append(JdbcSqlUtils.resolveSqlCondition(entry.getValue().toString()));
		}
		return this;
	}

	@Override
	public QueryBuilder between(String propertyName, Object lo, Object hi) {
		return null;
	}

	@Override
	public QueryBuilder eq(String propertyName, Object value) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public QueryBuilder eqProperty(String propertyName, String otherPropertyName) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public QueryBuilder fetch(String propertyTable, Object... args) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public QueryBuilder ge(String propertyName, Object value) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public QueryBuilder gt(String propertyName, Object value) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public QueryBuilder ilike(String propertyName, Object value,
			MatchMode matchMode) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public QueryBuilder ilike(String propertyName, Object value) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public QueryBuilder in(String propertyName, Object[] values) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public QueryBuilder in(String propertyName, Collection values) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Object invoke(Object... objs) {
		return sqlBuilder.toString();
	}

	@Override
	public QueryBuilder isNotNull(String propertyName) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public QueryBuilder isNull(String propertyName) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public QueryBuilder le(String propertyName, Object value) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public QueryBuilder leProperty(String propertyName, String otherPropertyName) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public QueryBuilder like(String propertyName, Object value) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public QueryBuilder like(String propertyName, Object value,
			MatchMode matchMode) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public QueryBuilder lt(String propertyName, Object value) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public QueryBuilder ltProperty(String propertyName, String otherPropertyName) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public QueryBuilder not(String propertyTable, HiCriteria hi) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public QueryBuilder notEq(String propertyName, Object value) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public QueryBuilder or(String propertyName, SymbolExpression expressions,
			Object[] objects) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public QueryBuilder or(String propertyName, SymbolExpression[] expressions,
			Object[] objects) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public QueryBuilder or(String[] propertyNames,
			SymbolExpression[] expressions, Object[] objects) {
		// TODO Auto-generated method stub
		return null;
	}
	
	protected void createTableColumn(String...selections ){
		for(String selection:selections){
			StringTokenizer st = new StringTokenizer(selection,".");
			int i=0;
			TableColumn tableColumn = null;
			while(st.hasMoreTokens()){
				String str = st.nextToken();
				if(i==0){
					tableColumn = new TableColumn(str);
					tableColumns.put(str, tableColumn);
				}else if(i==1){
					tableColumn.getColumns().add(str);
				}
				i++;
			}
		}
	}
	
	protected void generateSql(){
		StringBuilder selectSb=new StringBuilder();
		StringBuilder fromSb=new StringBuilder();
		
		sqlBuilder.append("SELECT ");
		
		for(TableColumn tc:tableColumns.values()){
			for(String column:tc.columns){
				selectSb.append(tc.getAlias()).append(".").append(column);
			}
			fromSb.append(tc.tableName).append(" ").append(tc.getAlias());
		}
		sqlBuilder.append(selectSb).append(" FROM ").append(fromSb);
	}
	
	private class TableColumn {
		private String tableName;
		private Set<String> columns;
		
		private int position = 0;
		
		public TableColumn(int position) {
			super();
			this.position = position;
		}

		public TableColumn() {
			super();
			columns = new HashSet<String>();
		}
		
		public TableColumn(String tableName) {
			super();
			this.tableName = tableName;
			columns = new HashSet<String>();
		}
		
		public TableColumn(String tableName, int position) {
			super();
			this.tableName = tableName;
			this.position = position;
		}

		public TableColumn(String tableName, Set<String> columns) {
			super();
			this.tableName = tableName;
			this.columns = columns;
		}

		public String getTableName() {
			return tableName;
		}
		public void setTableName(String tableName) {
			this.tableName = tableName;
		}
		public Set<String> getColumns() {
			return columns;
		}
		public void setColumns(Set<String> columns) {
			this.columns = columns;
		}
		
		public void addColumn(String column){
			columns.add(column);
		}

		public String getAlias() {
			return tableName.toLowerCase()+"_"+position;
		}
	}
	
	/**
	 * 
	 * @param <E>
	 * @param selections  tableName.propertyName eg: boo.id 
	 * @return
	 */
	public static <E> JdbcQueryBuilder forClass(Class clazz) {
		return new JdbcQueryBuilder(clazz);
	}

	@Override
	@Ignore
	protected QueryBuilder createMe() {
		return new JdbcQueryBuilder<T>(clazz);
	}

	@Override
	public QueryBuilder or(HiCriteria... criterias) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	protected QueryBuilder create(Class clzz) {
		return new JdbcQueryBuilder<T>(clzz);
	}

	@Override
	public QueryBuilder setDistinct(String obj) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public QueryBuilder setProperty(String... objs) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public QueryBuilder or(String subKey, HiCriteria... criterias) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public String getDistinct() {
		// TODO Auto-generated method stub
		return null;
	}

}
